/*************************************************************************
 *  Copyright © 2023-2030 FXB CO.,LTD. All rights reserved.
 *------------------------------------------------------------------------
 *  公司：Fxb
 *  项目：FXB-AutoDrive
 *  文件：SceneViewMenuDrawer.cs
 *  作者：Administrator
 *  日期：2024/8/30 14:56:51
 *  功能：Nothing
*************************************************************************/

using SceneViewMenu.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;

namespace SceneViewMenu.Editor
{
    /// <summary>
    /// 场景视图中绘制行为菜单
    /// </summary>
    public static class SceneViewMenuDrawer
    {
        private static Dictionary<ActionMenuItem, WindowActionItemList> MenuItems = new();

        /// <summary>
        /// 绘制菜单
        /// </summary>
        [InitializeOnLoadMethod]
        private static void DrawActionMenus()
        {
            SceneView.duringSceneGui += (SceneView sceneView) =>
            {
                Handles.BeginGUI();

                EditorGUILayout.BeginHorizontal();

                DrawActionMenuFirstLevel();

                DrawActionMenuSecondLevel();

                GUILayout.FlexibleSpace();

                EditorGUILayout.EndHorizontal();

                Handles.EndGUI();
            };
        }

        /// <summary>
        /// 初始化场景视图菜单
        /// </summary>
        [InitializeOnLoadMethod]
        private static void InitializeSceneMenuItems()
        {
            AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(assembly => assembly.GetTypes())
            .SelectMany(type => type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
            .Where(method => method.GetCustomAttributes(typeof(SceneViewMenuAttribute), false).Length > 0).ToList()
            .ForEach(method => {
                var attribute = method.GetCustomAttribute<SceneViewMenuAttribute>();
                var action = (Action)Delegate.CreateDelegate(typeof(Action), method);
                Add(attribute.MenuName, action);
            });
        }

        /// <summary>
        /// 绘制一级菜单
        /// </summary>
        private static void DrawActionMenuFirstLevel()
        {
            GUIStyle style = new GUIStyle("Button") { wordWrap = true, contentOffset = new Vector2(0, -6), };

            EditorGUILayout.BeginVertical();
            foreach (var item in MenuItems)
            {
                GUIContent content = new GUIContent(item.Key.actionName);

                GUI.color = item.Key.isToggle ? Color.white : new Color(0.6f, 0.6f, 0.6f);

                if (GUILayout.Button(content, style, GUILayout.Width(22), GUILayout.Height(style.CalcHeight(content, 22))))
                {
                    SelectToggleChanged(item.Key);

                    if (item.Value.Count == 0)
                        item.Key.action?.Invoke();
                }

                GUI.color = Color.white;
            }
            EditorGUILayout.EndVertical();
        }

        /// <summary>
        /// 绘制二级菜单
        /// </summary>
        private static void DrawActionMenuSecondLevel()
        {
            foreach (var item in MenuItems)
            {
                if (item.Key.isToggle)
                    item.Value.DrawActionItems();
            }
        }

        /// <summary>
        /// 选择改变
        /// </summary>
        /// <param name="actionMenu"></param>
        public static void SelectToggleChanged(ActionMenuItem actionMenu)
        {
            foreach (var item in MenuItems)
            {
                item.Key.isToggle = item.Value.Count == 0 ? false : (item.Key == actionMenu ? !item.Key.isToggle : false);
            }
        }

        /// <summary>
        /// 添加菜单
        /// </summary>
        /// <param name="menu"></param>
        /// <param name="action"></param>
        public static void Add(string menu, Action action = null)
        {
            Match match = Regex.Match(menu, @"^(.*)/(.*)$|^(.*)$");
            if (match.Success)
            {
                List<Group> groups = match.Groups.Where(item => !string.IsNullOrEmpty(item.Value)).ToList();

                ActionMenuItem item = MenuItems.Keys.FirstOrDefault(item => item.actionName == groups[1].Value);

                if (item == null)
                {
                    item = new ActionMenuItem(groups[1].Value, action);
                    MenuItems[item] = new WindowActionItemList();
                }

                if (groups.Count > 2)
                {
                    if (!MenuItems[item].IsContainActionItem(groups[2].Value))
                    {
                        MenuItems[item].Add(new ActionMenuItem(groups[2].Value, action));
                    }
                }
            }
        }

        /// <summary>
        /// 行为菜单项
        /// </summary>
        public class ActionMenuItem
        {
            public bool isToggle { get; set; }
            public string actionName { get; set; }
            public Action action { get; set; }

            public ActionMenuItem(string name, Action action)
            {
                this.actionName = name;
                this.action = action;
            }
        }
    }
}


